-- tablecmd.lua 处理其他service的调用,主要是
-- 桌子的命令，就是 start， reload， delete ,核心是去调用 tablelogic 的函数
local filename = "tablecmd.lua"

local skynet = require "skynet"

local filelog = require "filelog"
local timetool = require "timetool"
local tabletool = require "tabletool"
local timer = require "timer"

local json = require "cjson"
json.encode_sparse_array(true, 1, 1)

require "pjenum"

local CMD = {}
local service = nil
local tablelogic = nil
local gamelogic = nil

function CMD.init(caller)
	service = caller
	tablelogic = service:get_logicbyname("tablelogic")
        gamelogic = service:get_logicbyname("gamelogic")
end

--
-- 处理cmd类型消息
--
function  CMD.cmd(subcmd,...)
    local f = CMD[subcmd]
    if f == nil then
        return
    end

    return f(...)
end

--------------------------------

--
-- 杀死服务
--
function CMD.kill_service(...)
	service:exit_service()
end

--
-- 从 nodecmd的 createtable()里面调用
--
function CMD.start(conf, attachconf)
	tablelogic.init_data(service.table_data, conf, attachconf)
	return true
end

--
-- 重新加载配置
--
function CMD.reload(conf)
	local table_data = service.table_data

	---判断桌子是否在游戏中,如果是在游戏中，将配置文件缓存
	if not tablelogic.is_gameend(table_data) then
		table_data.backofconf = tabletool.deepcopy(conf)
		return
	end
	for key, value in pairs(conf) do
		table_data.conf[key] = value 
	end
end

--
--删除桌子
--
function CMD.delete(delete_reason)
    filelog.print("-----------------CMD.delete")

	local table_data = service.table_data
	table_data.isdeleting = true
	--踢出座位上的玩家
	tablelogic.leavetableallplayer(table_data, EStandupReason.STANDUP_REASON_DELETE_TABLE)
	local waits = tabletool.deepcopy(table_data.waits) or { }
	for rid, waitinfo in pairs(waits) do
		tablelogic.passive_leavetable(table_data, rid, waitinfo.playerinfo.diamond)
	end
	
    local table_index = table_data.index	

     --保存桌子记录
    if table_data.game_records ~= nil then
        table_data.game_records.delete_time = timetool.get_time()
        if delete_reason ~= nil then
            table_data.game_records.delete_reason = delete_reason
        end
        tablelogic.save_table_final_records(table_data)
    end

    --通知router删除table
	skynet.call(".router", "lua", "delete_table", nil,table_index)

    --删除桌子前清除桌子的状态
	tablelogic.clear(table_data)
	
    --关闭服务
	service:exit_service()
end

--
-- 获得桌子数据
--
function CMD.get_table_data()
    local tableobj = service.table_data
    local data = {
        table_index	= tableobj.index,
		table_code	= tableobj.code,
		conf	= tableobj.conf,
		cur_player	= tableobj.sitdown_player_num,
		create_time	= tableobj.create_time,
        create_rid = tableobj.create_rid,
        history_prize_list = tableobj.game_records.history_prize_list,
        table_state = tableobj.state,
    }

    --设置状态超时时间,结算--下注--开牌---结算--下注
    local DOBET = EPJTableState.TABLE_STATE_WAIT_SHAKE_DICE
    -- local DOBET = EPJTableState.TABLE_STATE_WAIT_OPENCARD_COUNTDOWN
    local OPENCARD = EPJTableState.TABLE_STATE_WAIT_HANDLE_OPENCARD_RESULT
    local BALANCE = EPJTableState.TABLE_STATE_WAIT_ONE_GAME_START
    if tableobj.table_type == EPJTableType.TABLE_TYPE_DIAMOND then
        if tableobj.timer_id == -1 then
            tableobj.action_timeout_time = timetool.get_time()
        end
    elseif tableobj.action_timeout_time == 0 then
        tableobj.action_timeout_time = timetool.get_time()
    end
    
    if tableobj.state == DOBET then           --下注中
        data.action_timeout_time = tableobj.action_timeout_time
    elseif tableobj.state == OPENCARD then    --开牌中
        data.action_timeout_time = tableobj.action_timeout_time
    elseif tableobj.state == BALANCE then     --结算中
        data.action_timeout_time = tableobj.action_timeout_time + 1
    elseif tableobj.state > DOBET and tableobj.state < OPENCARD then       --等待开牌中
        data.table_state = OPENCARD
        data.action_timeout_time = tableobj.action_timeout_time + 6
    elseif tableobj.state > BALANCE and tableobj.state < DOBET then        --等待下注中
        if tableobj.table_type ~= EBJLTableType.TABLE_TYPE_ZRSX then
            data.table_state = DOBET
            data.action_timeout_time = tableobj.action_timeout_time + tableobj.do_bet_timeout
        else
            data.table_state = BALANCE
            data.action_timeout_time = tableobj.action_timeout_time
        end
    elseif tableobj.state > OPENCARD and tableobj.state < BALANCE then     --等待结算中
        data.table_state = BALANCE
        data.action_timeout_time = tableobj.action_timeout_time + 5
    else
        data.table_state = BALANCE
        data.action_timeout_time = tableobj.action_timeout_time
    end

   return data
end

--
-- 获得所有rids
--
function CMD.get_table_allrid()
    local rids = { }
    local tableobj = service.table_data

    for _,seat in pairs(tableobj.seats) do
        if seat.state == EPJSeatState.SEAT_STATE_NO_PLAYER 
        or not seat.rid or seat.rid <= 0  then
        
        else
            table.insert(rids,seat.rid)
        end
    end
    for _,w in pairs(tableobj.waits) do
        table.insert(rids,w.rid)
    end
    
   return rids
end

--
-- 获得公开桌列表
-- 正常不会收到，容错处理
--
function CMD.getpubtablelist(rid, roledata)
    return skynet.call(".router","lua","getpubtablelist",nil,rid,roledata)
end

--
-- 获得桌子状态:人数和状态
--
function CMD.gettablestate()
    local tableobj = service.table_data
    local sitdown_num = 0
    local robot_num = 0
    local watch_num = tableobj.cur_watch_playernum or 0
    local max_player_num = tableobj.conf.max_player_num or 0
    local delete_timer = tableobj.delete_table_timer_id or -1
    local is_deleteing = false
    if delete_timer > 0 or tableobj.isdeleting then
        is_deleteing = true
    end

    --获得坐下人数
    for _,seat in pairs(tableobj.seats) do
        if seat.state <= EPJSeatState.SEAT_STATE_NO_PLAYER or seat.rid <= 0 then
            
        else
            sitdown_num = sitdown_num + 1
            if seat.is_robot then
                robot_num = robot_num + 1
            end
        end
    end
    
    local msg = {
        cur_player_num = sitdown_num + watch_num,       --当前桌内人数
        watch_player_num = watch_num,                   --当前旁观人数
        max_player_num = max_player_num,                --桌子支持最大人数
        table_state = tableobj.state,                   --桌子状态
        last_heart_time = tableobj.last_heart_time,     --上次心跳时间
        is_ingame = tableobj.is_ingame,                 --是否游戏中
        is_deleteing = is_deleteing,                    --是否删除中
        table_type = tableobj.table_type,               --桌子类型
        level_type = tableobj.level_type,               --场次类型
        robot_num = robot_num,                          --机器人数量
    }
    return msg
end

--
-- 定时删除桌子
--
function CMD.delete_table_by_timer()
    local tableobj = service.table_data
    tableobj.delete_table_timer_id = tableobj.delete_table_timer_id or -1
    if tableobj.isdeleting or tableobj.delete_table_timer_id > 0 then
        return
    end

    tableobj.delete_table_timer_id = timer.settimer(5,"delete_table")
    if tableobj.delete_table_timer_id < 0 then  --设置定时器失败,则直接删除
        CMD.delete(EPJTableDeleteReason.DELETE_REASON_SYSTEM_ERROR)
    end
end

--
-- 设置桌子结束标记,标记后在一局结束后桌子将被删除
--
function CMD.set_tableend_flag()
    service.table_data.tableend_flag = true

    --如果桌子还未开始游戏直接删除
    if service.table_data.state == EPJTableState.TABLE_STATE_WAIT_PLAYER_SITDOWN
    or service.table_data.state == EPJTableState.TABLE_STATE_WAIT_ALL_READY then
        CMD.delete(EPJTableDeleteReason.DELETE_REASON_SYSTEM_REQUIRE)
    end
end

--
--检测桌子状态
--
function  CMD.check_tablestate()
    local tableobj = service.table_data

    --桌子删除中
    if tableobj.isdeleting then
        return false
    end

    --桌子空位数
    local empty_seat_num = tableobj.conf.max_player_num - tableobj.sitdown_player_num

    return empty_seat_num
end

--
--延时离桌
--
function CMD.delay_leave(rid)
    local tableobj = service.table_data

    --游戏中才需要延时离桌
    if not tableobj.is_ingame then
        return false
    end

    for _,seat in pairs(tableobj.seats) do
        if seat.rid == rid then
            seat.is_delayleave = true
            break
        end
    end

    return true
end

--
--获取玩家列表
--
function CMD.get_player_list()
    local tableobj = service.table_data
    local player_list = {}
    for _,seat in pairs(tableobj.seats) do
        if seat.state <= EPJSeatState.SEAT_STATE_NO_PLAYER or seat.rid <= 0 then    
        else
            local item = {
                rid = seat.rid,
                logo = seat.playerinfo.logo,
                rolename = seat.playerinfo.rolename,
                game_num = seat.play_game_num,
            }
            table.insert(player_list,item)
        end
    end
    
    return player_list
end

--
--开奖
--
function CMD.open_jackpot(msg)
    local tableobj = service.table_data
    tableobj.open_jackpot_timestamp = msg.open_jackpot_timestamp
    tablelogic.sendmsg_to_alltableplayer(tableobj,"openjackpotN",msg)

    --重置游戏次数
    for _,seat in pairs(tableobj.seats) do
        if seat.state > EPJSeatState.SEAT_STATE_NO_PLAYER then    
            seat.play_game_num = 0
        end
    end

    --修改金钱
    for _,awarditem in pairs(msg.openjackpot_list) do
        local seat = tablelogic.get_seat_by_rid(tableobj,awarditem.rid)
        if seat then
            if tableobj.table_type == EPJTableType.TABLE_TYPE_DIAMOND then
                seat.playerinfo.diamond = seat.playerinfo.diamond + awarditem.award_money_num
            elseif tableobj.table_type == EPJTableType.TABLE_TYPE_COIN then
                seat.playerinfo.coin = seat.playerinfo.coin + awarditem.award_money_num
            else
                seat.playerinfo.diamond = seat.playerinfo.diamond + awarditem.award_money_num
            end
        end
    end
end

--
--更新游戏数据
--
function CMD.update_gamedata(gamedata)
    local tableobj = service.table_data
    local evtmsg = json.decode(gamedata or "{}")
    if not evtmsg then
        return
    end
    
    --处理消息，并通知客户端
    local result = tablelogic.handle_gamedata(tableobj, evtmsg)
    if result then
        local noticemsg = {
            game_state = evtmsg.cmd,
        }
        tablelogic.sendmsg_to_alltableplayer(tableobj, "gamestatechangeN", noticemsg)
    end
end

return CMD